package com.example.demo;

import java.util.Locale;

/**
 * 紫微计算器
 * - 公历/农历转换
 * - 年柱、月柱、日柱、时柱精确计算
 * - 命宫定位、主星入宫、四化飞星、格局识别
 */
public class ZiWeiCalculatorProfessional {
    static final String[] TG = {"甲","乙","丙","丁","戊","己","庚","辛","壬","癸"};
    static final String[] DZ = {"子","丑","寅","卯","辰","巳","午","未","申","酉","戌","亥"};
    static final String[] PALACE = {"命宫","兄弟","夫妻","子女","财帛","疾厄","迁移","仆役","官禄","田宅","福德","父母"};
    static final String[] MAIN_STARS = {"紫微","天机","太阳","武曲","天同","廉贞","天府","太阴","贪狼","巨门","天相","天梁","七杀","破军"};

    public static class Result {
        public String yearGanZhi;
        public String monthGanZhi;
        public String dayGanZhi;
        public String hourGanZhi;
        public String[] palaceStars = new String[12];
        public String analysisText = "";

        // 新增：每宫详细分析
        public String[] palaceAnalysis = new String[12];  // 宫位分析文字
        public int[] palaceLuck = new int[12]; // 1=吉,0=中性,-1=凶


        public String toJson() {
            StringBuilder sb = new StringBuilder();
            sb.append(yearGanZhi).append("|")
                    .append(monthGanZhi).append("|")
                    .append(dayGanZhi).append("|")
                    .append(hourGanZhi).append("|");
            for (int i = 0; i < 12; i++) {
                sb.append(palaceStars[i].replace('|','/'));
                if (i < 11) sb.append(",");
            }
            sb.append("|").append(analysisText.replace('|','/'));
            return sb.toString();
        }

        public static Result fromJson(String s) {
            Result r = new Result();
            try {
                String[] parts = s.split("\\|");
                r.yearGanZhi = parts[0];
                r.monthGanZhi = parts[1];
                r.dayGanZhi = parts[2];
                r.hourGanZhi = parts[3];
                String[] ps = parts[4].split(",");
                for (int i = 0; i < 12 && i < ps.length; i++) r.palaceStars[i] = ps[i];
                if (parts.length > 5) r.analysisText = parts[5];
            } catch (Exception e) { }
            return r;
        }
    }

    /**
     * 计算紫微排盘
     * @param year 公历年
     * @param month 月
     * @param day 日
     * @param hour 小时（本地时间）
     * @param minute 分钟
     * @param longitudeDegrees 经度（东经为正）
     * @param isLunar 是否为农历
     * @return Result
     */
    public static Result compute(int year,int month,int day,int hour,int minute,double longitudeDegrees, boolean isLunar) {
        Result chart = new Result();

        // 1️⃣ 农历转换
        if (isLunar) {
            double jd = LunarConverter.lunarToJulianDay(year, month, false, day);
            int[] ymd = JulianToGregorian(jd);
            year = ymd[0]; month = ymd[1]; day = ymd[2];
        }

        // 2️⃣ 构造儒略日
        double dayFraction = (hour + minute/60.0)/24.0;
        double jd = AstronomyUtils.toJulianDayUTC(year, month, day + dayFraction);

        // 3️⃣ 年柱
        int yoff = year - 4;
        chart.yearGanZhi = TG[mod(yoff,10)] + DZ[mod(yoff,12)];

        // 4️⃣ 月柱：以节气黄经判断
        double sunLon = AstronomyUtils.solarLongitude(jd);
        int monthIndex = (int)Math.floor(((sunLon+30)%360)/30); // 0..11
        int monthStemIndex = mod(yoff*2 + monthIndex, 10);
        int monthBranchIndex = mod(monthIndex+2,12);
        chart.monthGanZhi = TG[monthStemIndex]+DZ[monthBranchIndex];

        // 5️⃣ 日柱
        int base = (int)Math.floor(jd+0.5);
        chart.dayGanZhi = TG[mod(base+6,10)] + DZ[mod(base+8,12)];

        // 6️⃣ 时柱：使用真太阳时
        double last = AstronomyUtils.localApparentSolarTimeHours(jd, longitudeDegrees);
        int hourBranchIndex = lastToHourBranchIndex(last);
        int hourStemIndex = mod(mod(base+6,10)*2 + hourBranchIndex,10);
        chart.hourGanZhi = TG[hourStemIndex]+DZ[hourBranchIndex];

        // 7️⃣ 命宫定位
        int mingIndex = mod(hourBranchIndex + monthBranchIndex,12);

        // 8️⃣ 主星入宫（紫微在命宫，其余顺排）
        for (int i = 0; i < 12; i++) chart.palaceStars[mod(mingIndex+i,12)] = MAIN_STARS[i%MAIN_STARS.length];

        // 9️⃣ 分析文字（示例，可扩展四化、格局识别）
        StringBuilder sb = new StringBuilder();
        sb.append(String.format(Locale.getDefault(),"年柱:%s 月柱:%s 日柱:%s 时柱:%s\n",
                chart.yearGanZhi,chart.monthGanZhi,chart.dayGanZhi,chart.hourGanZhi));
        sb.append("命宫:").append(PALACE[mingIndex]).append(" 主星:").append(chart.palaceStars[mingIndex]).append("\n");
        if ("紫微".equals(chart.palaceStars[mingIndex])) sb.append("格局提示:命宫有紫微，主领导才能、威望。\n");
        chart.analysisText = sb.toString();

        for (int i = 0; i < 12; i++) {
            String star = chart.palaceStars[i];
            StringBuilder sb1 = new StringBuilder();
            sb1.append(star).append("宫：");

            switch (star) {
                case "紫微":
                    sb1.append("主权威、领导、稳重。");
                    chart.palaceLuck[i] = 1;
                    break;
                case "天机":
                    sb1.append("智慧灵活、善变。");
                    chart.palaceLuck[i] = 0;
                    break;
                case "破军":
                    sb1.append("冲动、易破财。");
                    chart.palaceLuck[i] = -1;
                    break;
                default:
                    sb1.append("性格与运势中性。");
                    chart.palaceLuck[i] = 0;
            }
            chart.palaceAnalysis[i] = sb1.toString();
        }


        return chart;
    }

    // 时支索引
    static int lastToHourBranchIndex(double lastHours) {
        int h = (int)Math.floor(lastHours);
        if (h == 23 || h == 0) return 0;
        if (h >= 1 && h <= 2) return 1;
        if (h >= 3 && h <= 4) return 2;
        if (h >= 5 && h <= 6) return 3;
        if (h >= 7 && h <= 8) return 4;
        if (h >= 9 && h <= 10) return 5;
        if (h >= 11 && h <= 12) return 6;
        if (h >= 13 && h <= 14) return 7;
        if (h >= 15 && h <= 16) return 8;
        if (h >= 17 && h <= 18) return 9;
        if (h >= 19 && h <= 20) return 10;
        return 11;
    }

    static int mod(int a,int b){int r=a%b;return r<0?r+b:r;}

    // 简单 JD -> 公历
    static int[] JulianToGregorian(double jd){
        int J = (int)(jd+0.5);
        int jalpha = (int)(((J-1867216)-0.25)/36524.25);
        int ja = J + 1 + jalpha - jalpha/4;
        int jb = ja + 1524;
        int jc = (int)(365.25*(jb-122.1));
        int jd_ = (int)(jb-jc);
        int je = (int)(jd_/30.6001);
        int day = jd_ - (int)(30.6001*je);
        int month = je-1;
        if (month>12) month-=12;
        int year = (int) Math.floor(jc / 365.25 - 4716);

        return new int[]{year,month,day};
    }
}
